// OGoMojo
// Whitemice.MOGI.RPC2.Appointment
// License: LGPL
// Copyright: Whitemice Consulting, 2006
// Author(s): Adam Tauno Williams (awilliam@whitemice.org)
using System;
using System.Collections;
using System.Globalization;
using Whitemice.MOGI;
using CookComputing.XmlRpc;

namespace Whitemice.MOGI.RPC2 {
	/// \brief Implements IAppointment
	public class Appointment : Whitemice.MOGI.RPC2.OwnedDocument, IAppointment {
		internal ArrayList	participants;
		/// \brief Constructor
		/// \param document An XmlRpcStruct document
		/// \param server Reference to server object
		public Appointment (XmlRpcStruct document, Server server)
		 : base(document, server) {
		 	server.Log.Debug("Appointment(...) - Name: " + this.Name);
		 	UpdateParticipants();
		}
		
		internal void UpdateParticipants()
		{
			participants = new ArrayList();
			Log.Debug("UpdateParticipants()");
		 	if (document.ContainsKey("participants"))
		 	{
		 		foreach(XmlRpcStruct participant in (Array)document["participants"])
		 			if(participant.ContainsKey("isPerson"))
		 				participants.Add("Document/Contact/" + participant["companyId"].ToString());
		 				else
		 					participants.Add("Document/Team/" + participant["companyId"].ToString());
		 		Log.Debug("Appointment has " + participants.Count + " participants");
		 	} else Log.Debug("Document does not contain a participants key");		
		}
		
		/// \brief Provides the unique name fo the object
		public override string Name {
			get {
				return ("Document/Appointment/" + Number);
			}
		}
		
		/// \brief Accessor for the title value
		public string Title {
			get {
				return (string)document["title"];
				
			}
			set {
				document["title"] = value;
			} 
		}
		
		/// \brief Accessor for the start datetime
		public DateTime Start {
			get {
		  		return (DateTime)document["startDate"];
			}
			set {
				document["startDate"] = value;
			}
		}
		
		/// \brief Accessor for the end datetime
		public DateTime End {
			get {
		  		return (DateTime)document["endDate"];
			}
			set {
				document["endDate"] = value;
			}
		}
		
		/// \brief Accessor for the comment value
		public string Comment {
			get {
				return (string)document["comment"];
			}
			set {
				document["comment"] = value;
			}
		}
		
		/// \brief Accessor for the location value
		public string Location {
			get {
				return (string)document["location"];
			}
			set {
				document["location"] = value;
			}
		}
		
		/// \brief Returns True if the appointment is cyclical
		public bool Cyclic {
			get {
				return document.ContainsKey("type");
			}
		}
		
		/// \brief Returns the cycle value of the appointment
		/// \note If the appointment is not cyclical this accessor returns "once"
		public string Cycle {
			get {
				if(Cyclic)
					return (string)document["type"];
					else return "once";
			}
			set
			{
				document["type"] = value;
			}
		}
		
		/// \brief Returns the date the cycle of the appointment ends
		public DateTime CycleEnd {
			get {
				//string startDate = document["cycleEndDate"].ToString();
		  		//startDate = startDate.Substring(0, startDate.IndexOf(' '));
		  		//return DateTime.ParseExact(startDate, "M/d/yyyy", new DateTimeFormatInfo());
		  		if (document.Contains("cycleEndDate"))
		  			return (DateTime)document["cycleEndDate"];
		  		return this.End;
			}
			set {
				document["cycleEndDate"] = value;
			}
		}
		
		/// \brief Accessor for the appointment type value
		public AppointmentType Class {
			get {
				AppointmentType appointmentType;
				appointmentType = AppointmentType.Unknown;
				string aptType = (string)document["aptType"]; 
				switch (aptType) {
					case "birthday":
						appointmentType = AppointmentType.Birthday;
						break;
					case "phone call":
						appointmentType = AppointmentType.PhoneCall;
						break;
					case "duedate":
						appointmentType = AppointmentType.DueDate;
						break;
					case "vacation":
						appointmentType = AppointmentType.Vacation;
						break;
					case "at home":
						appointmentType = AppointmentType.AtHome;
						break;
					case "ill":
						appointmentType = AppointmentType.Ill;
						break;
					case "meeting":
						appointmentType = AppointmentType.Meeting;
						break;
					case "all types":
						appointmentType = AppointmentType.AllTypes;
						break;
					case "outward":
						appointmentType = AppointmentType.Outward;
						break;
			        case "tradeshow":
			        	appointmentType = AppointmentType.TradeShow;
			        	break;			
				}
				return appointmentType;
			}
			set {
				switch (value) {
					case AppointmentType.Birthday:
						document["aptType"] = "birthday";
						break;
					case AppointmentType.PhoneCall:
						document["aptType"] = "phone call";
						break;
					case AppointmentType.DueDate:
						document["aptType"] = "duedate";
						break;
					case AppointmentType.Vacation:
						document["aptType"] = "vacation";
						break;
					case AppointmentType.AtHome:
						document["aptType"] = "at home";
						break;
					case AppointmentType.Ill:
						document["aptType"] = "ill";
						break;
					case AppointmentType.Meeting:
						document["aptType"] = "meeting";
						break;
					case AppointmentType.AllTypes:
						document["aptType"] = "all types";
						break;
					case AppointmentType.Outward:
						document["aptType"] = "outward";
						break;
			        case AppointmentType.TradeShow:
			        	document["aptType"] = "tradeshow";
			        	break;
			        default:
			        	document["aptType"] = "all types";
			        	break;
				}			
			}
		}
		public ArrayList Participants 
		{ 
			get	{ return participants; }
		}
		
		/// \todo Implement
		public void AddParticipant(string documentId)
		{
			if (!IsParticipant(documentId))
			{
				if((MOGI.DetermineType(documentId) == DocumentType.Contact) ||
					(MOGI.DetermineType(documentId) == DocumentType.Team))
				{
					Log.Debug("Adding Participant");
					participants.Add(documentId);
				}
			} else Log.Debug("Document is already a participant");	
		}
		
		/// \todo Implement
		public void AddParticipant(string documentId, ParticipantRole role)
		{
			throw new NotSupportedException("Backend does not support removing this document type");
		}
		
		/// \todo Implement
		public void RemoveParticipant(string documentId)
		{
			foreach(string p in participants)
				if (p == documentId) 
				{
					participants.Remove(p);
					return;
				}
		}
		
		/// \todo Implement
		public bool IsParticipant(string documentId)
		{
			Log.Debug("IsParticipant(" + documentId + ")");
			return participants.Contains(documentId);
		}
		
		/// \todo Implement
		public ParticipantRole ParticipantsRole(string participant)
		{
			return ParticipantRole.Unknown;
		}
		
		public ParticipantStatus ParticipantsStatus(string participant)
		{
			return ParticipantStatus.Unknown;
		}
		
		public void ClearParticipants()
		{
			participants.Clear();
		}
	}
}		